package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.OptionalRangeEnum;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.PaasFormHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.PaasProcessDataModel;
import com.xbongbong.paas.pojo.KeyValuePojo;
import com.xbongbong.paas.service.AssociationService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.WorkOrderErrorCodeEnum;
import com.xbongbong.pro.log.pojo.DetailLogPojo;
import com.xbongbong.pro.menu.pojo.dto.MenuInitDTO;
import com.xbongbong.pro.workorder.pojo.WorkOrderCategorySortPojo;
import com.xbongbong.pro.workorder.pojo.WorkOrderTemplateCommentTypePojo;
import com.xbongbong.pro.workorder.pojo.WorkOrderTemplateDetailFlowPojo;
import com.xbongbong.pro.workorder.pojo.WorkOrderTemplateDetailInfoPojo;
import com.xbongbong.pro.workorder.pojo.WorkOrderTemplateDetailWorkflowPojo;
import com.xbongbong.pro.workorder.pojo.WorkOrderTemplateListCategoryPojo;
import com.xbongbong.pro.workorder.pojo.WorkOrderTemplateListNodePojo;
import com.xbongbong.pro.workorder.pojo.WorkOrderTemplatePowerPojo;
import com.xbongbong.pro.workorder.pojo.WorkOrderTemplateTypePojo;
import com.xbongbong.pro.workorder.pojo.dto.WorkOrderTemplateCategoryDelDTO;
import com.xbongbong.pro.workorder.pojo.dto.WorkOrderTemplateCategorySaveDTO;
import com.xbongbong.pro.workorder.pojo.dto.WorkOrderTemplateCategorySortDTO;
import com.xbongbong.pro.workorder.pojo.dto.WorkOrderTemplateDelDTO;
import com.xbongbong.pro.workorder.pojo.dto.WorkOrderTemplateDetailDTO;
import com.xbongbong.pro.workorder.pojo.dto.WorkOrderTemplateEnableDTO;
import com.xbongbong.pro.workorder.pojo.dto.WorkOrderTemplateSaveDTO;
import com.xbongbong.pro.workorder.pojo.vo.WorkOrderTemplateCategoryDelVO;
import com.xbongbong.pro.workorder.pojo.vo.WorkOrderTemplateCategorySaveVO;
import com.xbongbong.pro.workorder.pojo.vo.WorkOrderTemplateCategorySortVO;
import com.xbongbong.pro.workorder.pojo.vo.WorkOrderTemplateDelVO;
import com.xbongbong.pro.workorder.pojo.vo.WorkOrderTemplateDetailVO;
import com.xbongbong.pro.workorder.pojo.vo.WorkOrderTemplateEnableVO;
import com.xbongbong.pro.workorder.pojo.vo.WorkOrderTemplateListVO;
import com.xbongbong.pro.workorder.pojo.vo.WorkOrderTemplateSaveVO;
import com.xbongbong.saas.domain.entity.WorkOrderEntity;
import com.xbongbong.saas.domain.entity.WorkOrderFormEntity;
import com.xbongbong.saas.domain.entity.WorkOrderStageEntity;
import com.xbongbong.saas.domain.entity.WorkOrderTemplateCategoryEntity;
import com.xbongbong.saas.domain.entity.WorkOrderTemplateEntity;
import com.xbongbong.saas.domain.entity.ext.WorkOrderFormEntityExt;
import com.xbongbong.saas.domain.entity.ext.WorkOrderTemplateEntityExt;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.WorkOrderStageRuleEnum;
import com.xbongbong.saas.enums.WorkOrderStatusEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.saas.model.WorkOrderModel;
import com.xbongbong.saas.model.WorkOrderStageModel;
import com.xbongbong.saas.model.WorkOrderTemplateCategoryModel;
import com.xbongbong.saas.model.WorkOrderTemplateModel;
import com.xbongbong.saas.service.WorkOrderFormService;
import com.xbongbong.saas.service.WorkOrderTemplateCategoryService;
import com.xbongbong.saas.service.WorkOrderTemplateService;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workorder.service.WorkOrderStageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 *
 * @author 魏荣杰
 * @date 2019/3/5 14:52
 * @since v1.0
 * @version v1.0
 */
@Service("workOrderTemplateService")
public class WorkOrderTemplateServiceImpl implements WorkOrderTemplateService {
    private static final Logger LOG = LoggerFactory.getLogger(WorkOrderTemplateServiceImpl.class);

    @Resource
    private WorkOrderTemplateModel workOrderTemplateModel;
    @Resource
    private WorkOrderTemplateCategoryModel workOrderTemplateCategoryModel;
    @Resource
    private WorkOrderStageModel workOrderStageModel;
    @Resource
    private UserModel userModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private WorkOrderTemplateCategoryService workOrderTemplateCategoryService;
    @Resource
    private WorkOrderModel workOrderModel;
    @Resource
    private WorkOrderFormService workOrderFormService;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private WorkOrderStageService workOrderStageService;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private LogHelp logHelp;
    @Resource
    private PaasProcessDataModel paasProcessDataModel;
    @Resource
    private AssociationService associationService;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private PaasFormHelp paasFormHelp;

    @Override
    public Long initTemplate(MenuInitDTO menuInitDTO, Long categoryId, UserEntity userEntity) throws XbbException {
        WorkOrderTemplateEntity workOrderTemplateEntity = new WorkOrderTemplateEntity();
        workOrderTemplateEntity.setCorpid(menuInitDTO.getCorpid());
        workOrderTemplateEntity.setAppId(menuInitDTO.getAppId());
        workOrderTemplateEntity.setCategoryId(categoryId);
        workOrderTemplateEntity.setName(I18nMessageUtil.getMessage(I18nStringConstant.AFTER_SALE));
        workOrderTemplateEntity.setIntroduction(I18nMessageUtil.getMessage(I18nStringConstant.SYSTEM_DEFAULT_TEMPLATE));
        workOrderTemplateEntity.setIsFree(1);
        workOrderTemplateEntity.setCc("[]");
        workOrderTemplateEntity.setEnable(1);
        workOrderTemplateEntity.setIsDefault(1);
        // TODO: 2019/3/13  格式修改
        JSONObject scopeRule = new JSONObject();
        scopeRule.put("inside", 1);
        scopeRule.put(OptionalRangeEnum.USER.getValue(), new JSONArray());
        scopeRule.put(OptionalRangeEnum.DEPT.getValue(),new JSONArray());
        workOrderTemplateEntity.setScopeRule(scopeRule.toJSONString());
        workOrderTemplateEntity.setCreatorId(userEntity.getUserId());
        workOrderTemplateEntity.setCreatorName(userEntity.getName());
        workOrderTemplateEntity.setModifierId(userEntity.getUserId());
        workOrderTemplateEntity.setModifierName(userEntity.getName());
        workOrderTemplateEntity.setExpectedTime(0);
        workOrderTemplateEntity.setDel(0);

        workOrderTemplateModel.insert(workOrderTemplateEntity);
        return workOrderTemplateEntity.getId();
    }

    @Override
    public WorkOrderTemplateListVO getListTree(String corpid, Long appId) throws XbbException {
        Map<String,Object> modelMap = new HashMap<>(16);
        modelMap.put("corpid",corpid);
        modelMap.put("del",0);
        modelMap.put("orderByStr","sort desc");
        modelMap.put("appId", appId);
        List<WorkOrderTemplateCategoryEntity> workOrderTemplateCategoryEntityList = workOrderTemplateCategoryModel.findEntitys(modelMap);

        modelMap.clear();
        modelMap.put("corpid",corpid);
        modelMap.put("del",0);
        modelMap.put("orderByStr","add_time asc");
        modelMap.put("appId", appId);
        List<WorkOrderTemplateEntityExt> workOrderTemplateEntityList = workOrderTemplateModel.findEntitys(modelMap);

        List<WorkOrderFormEntity> workOrderFormEntityExtList = workOrderFormModel.findEntitys(modelMap);
        Map<Long, Long> templateIdAndFormIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (WorkOrderFormEntity entity : workOrderFormEntityExtList) {
            templateIdAndFormIdMap.put(entity.getTemplateId(), entity.getId());
        }

        List<WorkOrderTemplateListCategoryPojo> categoryPojos = new ArrayList<>();
        for (WorkOrderTemplateCategoryEntity category : workOrderTemplateCategoryEntityList){
            WorkOrderTemplateListCategoryPojo workOrderTemplateListCategoryPojo = new WorkOrderTemplateListCategoryPojo();
            workOrderTemplateListCategoryPojo.setCategoryId(category.getId());
            workOrderTemplateListCategoryPojo.setName(category.getName());
            workOrderTemplateListCategoryPojo.setNameEn(category.getNameEn());
            workOrderTemplateListCategoryPojo.setNode(getSubTemplate(category.getId(), workOrderTemplateEntityList, templateIdAndFormIdMap));

            categoryPojos.add(workOrderTemplateListCategoryPojo);
        }
        WorkOrderTemplateListVO workOrderTemplateListVO = new WorkOrderTemplateListVO();
        workOrderTemplateListVO.setTemplateTree(categoryPojos);
        return workOrderTemplateListVO;
    }

    /**
     * 获得分类下模板
     * 添加时间 2017/10/25
     * @author haibin.zhang
     * @param categoryId 分类id
     * @param entityList 工单模板list
     * @return jsonArray 分类下的模板集合
     * @since 3.13
     * */
    private List<WorkOrderTemplateListNodePojo> getSubTemplate(Long categoryId,List<WorkOrderTemplateEntityExt> entityList, Map<Long, Long> templateIdAndFormIdMap){
        List<WorkOrderTemplateListNodePojo> nodePojoList = new ArrayList<>();
        for (WorkOrderTemplateEntity entity : entityList){
            WorkOrderTemplateListNodePojo nodePojo = new WorkOrderTemplateListNodePojo();
            if (entity.getCategoryId().equals(categoryId)){
                nodePojo.setName(entity.getName());
                nodePojo.setId(entity.getId());
                nodePojo.setIsEnable(entity.getEnable());
                nodePojo.setFormId(templateIdAndFormIdMap.get(entity.getId()));
                nodePojoList.add(nodePojo);
            }
        }
        return nodePojoList;
    }

    @Override
    public WorkOrderTemplateCategorySaveVO saveCategory(WorkOrderTemplateCategorySaveDTO workOrderTemplateCategorySaveDTO) throws XbbException {
        Long id = workOrderTemplateCategorySaveDTO.getId();
        String name = workOrderTemplateCategorySaveDTO.getName();
        String corpid = workOrderTemplateCategorySaveDTO.getCorpid();
        Long appId = workOrderTemplateCategorySaveDTO.getAppId();
        String userId = workOrderTemplateCategorySaveDTO.getUserId();
        String userName = workOrderTemplateCategorySaveDTO.getLoginUserName();

        Map<String, Object> param = new HashMap<>(16);
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("name", name);
        if (id >= 0) {
            param.put("negId", id);
        }
        Integer count = workOrderTemplateCategoryModel.getEntitysCount(param);
        if (count > 0) {
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222038);
        }

        param.clear();
        param.put("corpid", corpid);
        param.put("del", 0);
        count = workOrderTemplateCategoryModel.getEntitysCount(param);

        WorkOrderTemplateCategoryEntity entity;
        boolean addFlag = false;
        String oldName = "";
        if (id <= 0) {
            entity = new WorkOrderTemplateCategoryEntity();
            addFlag = true;
            entity.setCorpid(corpid);
            entity.setIsDefault(0);
            entity.setSort(count);
            entity.setName(name);
            entity.setNameEn(workOrderTemplateCategorySaveDTO.getNameEn());
            entity.setCreatorId(userId);
            entity.setCreatorName(userName);
            entity.setAppId(appId);
            entity.setDel(0);
        } else {
            entity = workOrderTemplateCategoryModel.getByKey(id, corpid);
            if (Objects.isNull(entity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
            }
            oldName = entity.getName();
            entity.setName(name);
            entity.setNameEn(workOrderTemplateCategorySaveDTO.getNameEn());
        }
        entity.setModifierId(userId);
        entity.setModifierName(userName);

        WorkOrderTemplateCategorySaveVO workOrderTemplateCategorySaveVO = new WorkOrderTemplateCategorySaveVO();
        workOrderTemplateCategorySaveVO.setId(workOrderTemplateCategoryModel.save(entity));
        // 记录日志
        String memo;
        OperateTypeEnum operateTypeEnum;
        if (addFlag) {
            operateTypeEnum = OperateTypeEnum.NEW;
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_FORM_WORK_ORDER_CATEGORY_ADD), userName, name);
        } else {
            operateTypeEnum = OperateTypeEnum.EDIT;
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_FORM_WORK_ORDER_CATEGORY_UPDATE), userName, name, oldName, name);
        }
        mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.WORK_ORDER, operateTypeEnum, id.toString(), name, memo, workOrderTemplateCategorySaveDTO.getHttpHeader());
        return workOrderTemplateCategorySaveVO;
    }

    @Override
    public WorkOrderTemplateCategoryDelVO delCategory(WorkOrderTemplateCategoryDelDTO workOrderTemplateCategoryDelDTO) throws XbbException {
        String corpid = workOrderTemplateCategoryDelDTO.getCorpid();
        Long id = workOrderTemplateCategoryDelDTO.getId();
        UserEntity userEntity = BeanUtil.copyProperties(workOrderTemplateCategoryDelDTO.getLoginUser(), UserEntity.class, false);
        WorkOrderTemplateCategoryEntity workOrderTemplateCategoryEntity = workOrderTemplateCategoryModel.getByKey(id, corpid);
        if (Objects.isNull(workOrderTemplateCategoryEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }
        if (workOrderTemplateCategoryEntity.getIsDefault().equals(1)) {
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222010);
        }
        //删除分类
        workOrderTemplateCategoryModel.deleteBykey(id, corpid);
        //分类下的模板移到默认分类下
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", workOrderTemplateCategoryDelDTO.getCorpid());
        param.put("isDefault", 1);
        param.put("del", 0);
        List<WorkOrderTemplateCategoryEntity> categoryEntities = workOrderTemplateCategoryModel.findEntitys(param);
        WorkOrderTemplateCategoryEntity category;
        Long categoryId;
        if (categoryEntities.isEmpty()) {
            categoryId = workOrderTemplateCategoryService.saveDefaultCategory(workOrderTemplateCategoryDelDTO.getAppId(), userEntity);
        } else {
            category = categoryEntities.get(0);
            categoryId = category.getId();
        }
        workOrderTemplateModel.moveToDefault(id, categoryId, corpid);

        // 记录日志
        String userName = workOrderTemplateCategoryDelDTO.getLoginUserName();
        String name = workOrderTemplateCategoryEntity.getName();
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_FORM_WORK_ORDER_CATEGORY_DELETE), userName, name);
        mongoLogHelp.buildLog(corpid, workOrderTemplateCategoryDelDTO.getUserId(), userName, OperateModuleTypeEnum.WORK_ORDER, OperateTypeEnum.DELETE, id.toString(), name, memo, workOrderTemplateCategoryDelDTO.getHttpHeader());

        WorkOrderTemplateCategoryDelVO workOrderTemplateCategoryDelVO = new WorkOrderTemplateCategoryDelVO();
        workOrderTemplateCategoryDelVO.setId(workOrderTemplateCategoryDelDTO.getId());
        return workOrderTemplateCategoryDelVO;
    }


    @Override
    public WorkOrderTemplateCategorySortVO sortCategory(WorkOrderTemplateCategorySortDTO workOrderTemplateCategorySortDTO) throws XbbException {
        List<WorkOrderCategorySortPojo> sortArray = workOrderTemplateCategorySortDTO.getSortArray();

        Map<Long, Long> sortMap = new HashMap<>(16);
        List<Long> idIn = new ArrayList<>();
        for (WorkOrderCategorySortPojo pojo : sortArray) {
            Long id = pojo.getId();
            Long sort = pojo.getSort();
            sortMap.put(id, sort);
            idIn.add(id);
        }
        Map<String, Object> param = new HashMap<>(16);
        param.put("idIn", idIn);
        param.put("corpid", workOrderTemplateCategorySortDTO.getCorpid());
        param.put("del", 0);
        try {
            workOrderTemplateCategoryModel.sortCategory(param, sortMap);
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        WorkOrderTemplateCategorySortVO workOrderTemplateCategorySortVO = new WorkOrderTemplateCategorySortVO();
        workOrderTemplateCategorySortVO.setIds(idIn);
        return workOrderTemplateCategorySortVO;
    }

    @Override
    public WorkOrderTemplateDetailVO getTemplateDetail(WorkOrderTemplateDetailDTO workOrderTemplateDetailDTO) throws XbbException {
        Long templateId = workOrderTemplateDetailDTO.getId();
        String corpid = workOrderTemplateDetailDTO.getCorpid();

        WorkOrderTemplateEntity templateEntity = workOrderTemplateModel.getBykey(templateId, corpid);
        if (Objects.isNull(templateEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }
        Long categoryId = templateEntity.getCategoryId();

        WorkOrderTemplateCategoryEntity categoryEntity = workOrderTemplateCategoryModel.getByKey(categoryId, corpid);

        List<WorkOrderTemplateDetailWorkflowPojo> workflowPojos = new ArrayList<>();
        if (Objects.equals(templateEntity.getIsFree(), 0)) {
            Map<String, Object> param = new HashMap<>(16);
            param.put("templateId", templateId);
            param.put("corpid", corpid);
            param.put("orderByStr", "sort");
            param.put("del", 0);
            List<WorkOrderStageEntity> workOrderStageEntityList = workOrderStageModel.findEntitys(param);
            for (WorkOrderStageEntity entity : workOrderStageEntityList) {
                WorkOrderTemplateDetailWorkflowPojo pojo = new WorkOrderTemplateDetailWorkflowPojo();
                pojo.setId(entity.getId());
                pojo.setName(entity.getName());
                pojo.setRefRobId(entity.getRefRobId());
                pojo.setRefRobName(entity.getRefRobName());
                pojo.setRefRobType(entity.getRefRobType());
                pojo.setUserAvatar(entity.getUserAvatar());
                pojo.setExpectedTime(entity.getExpectedTime() / 3600D);
                pojo.setIsLast(entity.getIsLast());
                pojo.setRuleId(entity.getRuleId());
                workflowPojos.add(pojo);
            }
        }


        WorkOrderTemplateDetailVO workOrderTemplateDetailVO = new WorkOrderTemplateDetailVO();
        WorkOrderTemplateDetailInfoPojo infoPojo = new WorkOrderTemplateDetailInfoPojo();
        infoPojo.setCategoryName(categoryEntity.getName());
        infoPojo.setTemplateName(templateEntity.getName());
        infoPojo.setTemplateNameEn(templateEntity.getNameEn());
        infoPojo.setIntroduction(templateEntity.getIntroduction());
        infoPojo.setCategoryId(templateEntity.getCategoryId());
        workOrderTemplateDetailVO.setInfo(infoPojo);

        WorkOrderTemplateDetailFlowPojo flowPojo = new WorkOrderTemplateDetailFlowPojo();
        WorkOrderTemplateTypePojo typePojo = new WorkOrderTemplateTypePojo();
        typePojo.setSelectedValue(templateEntity.getIsFree().equals(0) ? new KeyValuePojo("0", I18nMessageUtil.getMessage(I18nStringConstant.DESIGNATION_PROCESS)) : new KeyValuePojo("1", I18nMessageUtil.getMessage(I18nStringConstant.FREE_ASSIGNMENT)));
        List<KeyValuePojo> types = new ArrayList<>();
        types.add(new KeyValuePojo("0", I18nMessageUtil.getMessage(I18nStringConstant.DESIGNATION_PROCESS)));
        types.add(new KeyValuePojo("1", I18nMessageUtil.getMessage(I18nStringConstant.FREE_ASSIGNMENT)));
        typePojo.setList(types);

        flowPojo.setType(typePojo);
        flowPojo.setWorkflow(workflowPojos);
        flowPojo.setCc(JsonHelperUtil.parseArray(templateEntity.getCc()));
        flowPojo.setExpectedTime(templateEntity.getExpectedTime() / 3600D);


        JSONObject scopeRuleObj = JsonHelperUtil.parseObject(templateEntity.getScopeRule());
        Integer inside = scopeRuleObj.getInteger("inside");
        String user = scopeRuleObj.getString(OptionalRangeEnum.USER.getValue());
        String dep = scopeRuleObj.getString(OptionalRangeEnum.DEPT.getValue());

        WorkOrderTemplatePowerPojo powerPojo = new WorkOrderTemplatePowerPojo();
        WorkOrderTemplateCommentTypePojo commentTypePojo = new WorkOrderTemplateCommentTypePojo();
        List<KeyValuePojo> commentTypes = new ArrayList<>();
        commentTypePojo.setSelectedValue(inside.equals(0) ? new KeyValuePojo("0", I18nMessageUtil.getMessage(I18nStringConstant.EXTERNAL_EVALUATION_WORK_ORDER)) : new KeyValuePojo("1", I18nMessageUtil.getMessage(I18nStringConstant.INTERNAL_EVALUATION_WORK_ORDER)));
        commentTypes.add(new KeyValuePojo("0", I18nMessageUtil.getMessage(I18nStringConstant.EXTERNAL_EVALUATION_WORK_ORDER)));
        commentTypes.add(new KeyValuePojo("1", I18nMessageUtil.getMessage(I18nStringConstant.INTERNAL_EVALUATION_WORK_ORDER)));
        commentTypePojo.setList(commentTypes);

        powerPojo.setCommentType(commentTypePojo);

        List<OptionalRangeEntity> optionalRangeEntities = new ArrayList<>();
        Map<String, Object> param = new HashMap<>(16);

        JSONArray userArray = JsonHelperUtil.parseArray(user);
        if (!userArray.isEmpty()) {
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("userIdIn", userArray);
            List<UserEntity> userEntities = userModel.findEntitys(param);
            for (UserEntity entity : userEntities) {
                OptionalRangeEntity optionalRangeEntity = new OptionalRangeEntity();
                optionalRangeEntity.setName(entity.getName());
                optionalRangeEntity.setId(entity.getUserId());
                optionalRangeEntity.setProperty(OptionalRangeEnum.USER.getValue());
                optionalRangeEntity.setEditable(1);
                optionalRangeEntities.add(optionalRangeEntity);
            }
        }

        JSONArray depArray = JsonHelperUtil.parseArray(dep);
        if (!depArray.isEmpty()) {
            param.clear();
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("idIn", depArray);
            List<DepartmentEntity> departmentEntities = departmentModel.findEntitys(param);
            for (DepartmentEntity entity : departmentEntities) {
                OptionalRangeEntity optionalRangeEntity = new OptionalRangeEntity();
                optionalRangeEntity.setName(entity.getName());
                optionalRangeEntity.setEditable(1);
                optionalRangeEntity.setProperty(OptionalRangeEnum.DEPT.getValue());
                optionalRangeEntity.setId(entity.getId().toString());
                optionalRangeEntities.add(optionalRangeEntity);
            }
        }

        powerPojo.setAuthorization(optionalRangeEntities);

        workOrderTemplateDetailVO.setWorkflow(flowPojo);
        workOrderTemplateDetailVO.setPower(powerPojo);

        workOrderTemplateDetailVO.setRule(WorkOrderStageRuleEnum.getRule());
        workOrderTemplateDetailVO.setIsEnable(templateEntity.getEnable());

        param.clear();
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("templateId", templateId);
        Integer count = workOrderModel.getEntitysCount(param);
        workOrderTemplateDetailVO.setIsUser(count > 0 ? 1 : 0);

        workOrderTemplateDetailVO.setAppId(workOrderTemplateDetailDTO.getAppId());
        WorkOrderFormEntityExt formEntity = workOrderFormModel.getByTemplateId(templateId, corpid);
        workOrderTemplateDetailVO.setMenuId(formEntity.getMenuId());
        workOrderTemplateDetailVO.setFormId(formEntity.getId());
        workOrderTemplateDetailVO.setSaasMark(SaasMarkEnum.SAAS.getCode());
        workOrderTemplateDetailVO.setBusinessType(XbbRefTypeEnum.WORK_ORDER.getCode());
        // 国际化白名单
        CompanyConfigEntity entity = companyConfigModel.getByConfigAlias(CompanyConfigEnum.I18N_WHITE.getAlias(), PaasConstant.DEFAULT_DATA_CORPID);
        String value = CompanyConfigEnum.I18N_WHITE.getValue();
        if (Objects.nonNull(entity)) {
            value = entity.getConfigValue();
        }
        List<String> whiteList = JsonHelperUtil.parseArray(value, String.class);
        boolean flag = CollectionsUtil.isNotEmpty(whiteList) && whiteList.contains(corpid);
        workOrderTemplateDetailVO.setMultiLang(flag);
        return workOrderTemplateDetailVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WorkOrderTemplateSaveVO saveTemplate(WorkOrderTemplateSaveDTO workOrderTemplateSaveDTO) throws XbbException {
        String corpid = workOrderTemplateSaveDTO.getCorpid();
        String userId = workOrderTemplateSaveDTO.getUserId();
        String userName = workOrderTemplateSaveDTO.getLoginUserName();
        Long appId = workOrderTemplateSaveDTO.getAppId();

        Long id = workOrderTemplateSaveDTO.getId();
        WorkOrderTemplateDetailInfoPojo infoPojo = workOrderTemplateSaveDTO.getInfo();
        WorkOrderTemplateDetailFlowPojo workflowPojo = workOrderTemplateSaveDTO.getWorkflow();
        WorkOrderTemplatePowerPojo powerPojo = workOrderTemplateSaveDTO.getPower();

        Double expectedTime = workflowPojo.getExpectedTime();
        if (expectedTime != null && expectedTime > 10000) {
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222056);
        }
        if (expectedTime != null){
            expectedTime = expectedTime * 3600;
        }

        boolean isNew = false;
        String oldName = "";
        WorkOrderTemplateEntity template;
        JSONObject oldObj = null;
        if (id <= 0) {
            template = new WorkOrderTemplateEntity();
            template.setCorpid(corpid);
            template.setCreatorId(userId);
            template.setCreatorName(userName);
            template.setDel(0);
            template.setIsDefault(0);
            template.setEnable(1);
            template.setAppId(appId);
            isNew = true;
        } else {
            template = workOrderTemplateModel.getBykey(id, corpid);
            if (Objects.isNull(template)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
            }
            oldName = template.getName();
            oldObj = JSONObject.parseObject(JSONObject.toJSONString(template));
        }
        template.setCategoryId(infoPojo.getCategoryId());
        template.setIntroduction(infoPojo.getIntroduction());
        String templateName = infoPojo.getTemplateName();
        if (templateName != null && templateName.length() >= 20) {
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222057);
        }
        template.setName(templateName);
        template.setNameEn(infoPojo.getTemplateNameEn());

        template.setExpectedTime((expectedTime != null &&expectedTime < 0) ? 0 : expectedTime.intValue());
        template.setCc(workflowPojo.getCc().toJSONString());

        template.setModifierId(userId);
        template.setModifierName(userName);
        KeyValuePojo typeSelect = workflowPojo.getType().getSelectedValue();
        boolean isFree = false;
        if (!isNew && !Objects.equals(template.getIsFree(), Integer.valueOf(typeSelect.getKey()))) {
            Map<String, Object> param = new HashMap<>();
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("templateId", template.getId());
            Integer count = workOrderModel.getEntitysCount(param);
            if (count > 0) {
                if (!Objects.equals(template.getIsFree(), Integer.valueOf(typeSelect.getKey()))) {
                    throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222064);
                }
            }
        }
        if (Objects.equals(typeSelect.getKey(), "0")) {
            template.setIsFree(0);
        } else {
            template.setIsFree(1);
            isFree = true;
        }
        //如果expectedTime是0的话，默认是不限时
        /*if (isFree) {
            if (expectedTime < 0.01) {
                throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222036.getCode(), String.format(WorkOrderErrorCodeEnum.API_ERROR_222036.getMsg(), "0.01"));
            }
        }*/
        //有工单在流转中的时候，工单流程不能修改
        if (!isNew && !isFree) {
            Map<String, Object> param1 = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param1.put("corpid", corpid);
            param1.put("del", 0);
            param1.put("templateId", template.getId());
            List<WorkOrderStageEntity> workOrderStageEntityList = workOrderStageModel.findEntitys(param1);
            //对比流程是否更改了
            Boolean result = contrastWorkOrderStage(workOrderStageEntityList, workflowPojo.getWorkflow());
            if (result) {
                List<Integer> statusList = new ArrayList<>();
                statusList.add(WorkOrderStatusEnum.UNACCEPTED.getCode());
                statusList.add(WorkOrderStatusEnum.ONGOING.getCode());
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("corpid", corpid);
                param.put("del", 0);
                param.put("templateId", template.getId());
                param.put("statusIn", statusList);
                param.put("flowStatusIn", Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.IN_APPROVAL.getType(), FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.PASS.getType()));
                Integer entitysCount = workOrderModel.getEntitysCount(param);
                if (entitysCount > 0) {
                    throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222068);
                }
            }
        }
        KeyValuePojo powerSelect = powerPojo.getCommentType().getSelectedValue();
        String powerSelectValue = powerSelect.getKey();
        List<String> userIds = new ArrayList<>();
        List<String> depIds = new ArrayList<>();
        List<OptionalRangeEntity> authorization = powerPojo.getAuthorization();
        for (OptionalRangeEntity entity : authorization) {
            if (Objects.equals(entity.getProperty(), OptionalRangeEnum.USER.getValue())) {
                userIds.add(entity.getId());
            } else if (Objects.equals(entity.getProperty(), OptionalRangeEnum.DEPT.getValue())) {
                depIds.add(entity.getId());
            }
        }

        JSONObject scopeRuleObj = new JSONObject();
        scopeRuleObj.put("inside", Objects.equals(powerSelectValue, "0") ? 0 : 1);
        scopeRuleObj.put(OptionalRangeEnum.USER.getValue(), userIds);
        scopeRuleObj.put(OptionalRangeEnum.DEPT.getValue(), depIds);
        template.setScopeRule(scopeRuleObj.toJSONString());

        try {
            workOrderTemplateModel.save(template);
            List<WorkOrderTemplateDetailWorkflowPojo> oldWorkStageList = new ArrayList<>();
            List<WorkOrderTemplateDetailWorkflowPojo> newWorkStageList = workflowPojo.getWorkflow();
            if (!isFree) {
                try {
                    //如果是指定流程，更新tb_work_order_stage数据
                    oldWorkStageList = workOrderStageService.saveStages(newWorkStageList, template.getId(), corpid, isNew);
                } catch (XbbException e) {
                    // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    throw e;
                }

            } else {
                // TODO: 2019/3/18
                //自由流程
                //如果修改了模板的预计耗时，更新tb_saas_work_order_data的expected_time字段

            }

            String opName = RedundantTemplateTypeEnum.WORKORDER.getName();
            //保存模板
            if (isNew) {
                //新建的模板需要生成tb_work_order_form和tb_work_order_explain相应数据
                workOrderFormService.saveDefaultFormAndExplain(corpid, workOrderTemplateSaveDTO.getUserId(), infoPojo, workOrderTemplateSaveDTO.getAppId(), template.getId());

                //新增工单模板日志
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_FORM_WORK_ORDER_ADD), userName, templateName);
                mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.WORK_ORDER, OperateTypeEnum.NEW, id.toString(), opName, memo, workOrderTemplateSaveDTO.getHttpHeader());
            } else {
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_FORM_WORK_ORDER_UPDATE), userName, templateName);
                JSONObject newObj = JSONObject.parseObject(JSONObject.toJSONString(template));
                //把工作详情流程的变更记录下来
                oldObj.put("workflow", oldWorkStageList);
                newObj.put("workflow", newWorkStageList);
                OperateModuleTypeEnum operateModuleType = OperateModuleTypeEnum.WORK_ORDER;
                List<DetailLogPojo> detailArr = logHelp.getDetailArr4Complex(corpid, operateModuleType, oldObj, newObj);
                mongoLogHelp.buildLog4DetailArr(detailArr, corpid, userId, userName, operateModuleType, OperateTypeEnum.EDIT, id.toString(), opName, memo, workOrderTemplateSaveDTO.getHttpHeader());
            }

            //如果编辑了模板名称需要同步修改tb_work_order_form的name字段
            if (!isNew && !Objects.equals(oldName, templateName)) {
                Map<String, Object> param = new HashMap<>(16);
                param.put("corpid", corpid);
                param.put("templateId", template.getId());
                param.put("del", 0);
                List<WorkOrderFormEntity> formEntities = workOrderFormModel.findEntitys(param);
                if (formEntities.size() > 0) {
                    WorkOrderFormEntity form = formEntities.get(0);
                    form.setName(templateName);
                    form.setNameEn(infoPojo.getTemplateNameEn());
                    workOrderFormModel.update(form);
                }
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("WorkOrderTemplateServiceImpl.saveTemplate 出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        WorkOrderTemplateSaveVO workOrderTemplateSaveVO = new WorkOrderTemplateSaveVO();
        workOrderTemplateSaveVO.setId(id);
        workOrderTemplateSaveVO.setCategoryId(template.getCategoryId());
        return workOrderTemplateSaveVO;
    }

    private Boolean contrastWorkOrderStage(List<WorkOrderStageEntity> workOrderStageEntityList, List<WorkOrderTemplateDetailWorkflowPojo> newWorkStageList) {
        Boolean result = true;
        LinkedList<String> oldList = new LinkedList<>();
        LinkedList<String> newList = new LinkedList<>();
        List<WorkOrderStageEntity> collect = workOrderStageEntityList.stream()
                .sorted(Comparator.comparing(WorkOrderStageEntity::getSort))
                .collect(Collectors.toList());
        for (WorkOrderStageEntity entity : collect) {
            oldList.add(entity.getName());
        }
        for (WorkOrderTemplateDetailWorkflowPojo pojo : newWorkStageList) {
            newList.add(pojo.getName());
        }
        if (Objects.equals(oldList, newList)) {
            result = false;
        }
        return result;
    }

    @Override
    public WorkOrderTemplateEnableVO enableTemplate(WorkOrderTemplateEnableDTO workOrderTemplateEnableDTO) throws XbbException {
        Long id = workOrderTemplateEnableDTO.getId();
        String corpid = workOrderTemplateEnableDTO.getCorpid();
        WorkOrderTemplateEntity workOrderTemplateEntity = workOrderTemplateModel.getBykey(id, corpid);
        if (Objects.isNull(workOrderTemplateEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }
        Integer enable = workOrderTemplateEnableDTO.getIsEnable();
        workOrderTemplateEntity.setEnable(enable);
        workOrderTemplateModel.save(workOrderTemplateEntity);

        WorkOrderFormEntity workOrderFormEntity = workOrderFormModel.getByTemplateId(workOrderTemplateEntity.getId(), workOrderTemplateEntity.getCorpid());
        workOrderFormEntity.setEnable(workOrderTemplateEnableDTO.getIsEnable());
        workOrderFormModel.update(workOrderFormEntity);

        WorkOrderTemplateEnableVO workOrderTemplateEnableVO = new WorkOrderTemplateEnableVO();
        workOrderTemplateEnableVO.setId(workOrderTemplateEnableDTO.getId());
        workOrderTemplateEnableVO.setCategoryId(workOrderTemplateEntity.getCategoryId());

        // 记录日志
        String memo;
        OperateTypeEnum operateType;
        String userName = workOrderTemplateEnableDTO.getLoginUserName();
        String formName = workOrderTemplateEntity.getName();
        if (Objects.equals(enable, 1)) {
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_FORM_WORK_ORDER_ENABLE), userName, formName);
            operateType = OperateTypeEnum.ENABLE;
        } else {
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_FORM_WORK_ORDER_CLOSE), userName, formName);
            operateType = OperateTypeEnum.CLOSE;
        }
        mongoLogHelp.buildLog(corpid, workOrderTemplateEnableDTO.getUserId(), userName, OperateModuleTypeEnum.WORK_ORDER, operateType, id.toString(), formName, memo, workOrderTemplateEnableDTO.getHttpHeader());
        return workOrderTemplateEnableVO;
    }

    @Override
    public WorkOrderTemplateDelVO delTemplate(WorkOrderTemplateDelDTO workOrderTemplateDelDTO) throws XbbException {
        Long templateId = workOrderTemplateDelDTO.getId();
        String corpid = workOrderTemplateDelDTO.getCorpid();
        Integer businessType = XbbRefTypeEnum.WORK_ORDER.getCode();
        WorkOrderTemplateEntity workOrderTemplateEntity = workOrderTemplateModel.getBykey(templateId, corpid);
        if (Objects.isNull(workOrderTemplateEntity) || Objects.equals(workOrderTemplateEntity.getDel(), 1)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }
        if (Objects.equals(workOrderTemplateEntity.getIsDefault(), 1)) {
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222034);
        }
        //当模版存在数据时，不给予删除的权限
        Map<String, Object> param = new HashMap<>(16);
        param.put("corpid", corpid);
        param.put("templateId", templateId);
        param.put("del", 0);
        List<WorkOrderFormEntity> formEntityExtList = workOrderFormModel.findEntitys(param);
        if (!formEntityExtList.isEmpty()) {
            WorkOrderFormEntity entityExt = formEntityExtList.get(0);
            Map<String, Object> param1 = new HashMap<>(16);
            param1.put("corpid", corpid);
            param1.put("formId", entityExt.getId());
            param1.put("del", 0);
            List<WorkOrderEntity> workOrderEntityList = workOrderModel.findEntitys(param1);
            if (workOrderEntityList.size() > 0) {
                throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222061);
            }
            boolean isOpenWorkflow = commonHelp.isOpenWorkFlow(corpid);
            if (isOpenWorkflow) {
                paasFormHelp.validateFormHasWorkflow(corpid, entityExt.getAppId(), entityExt.getMenuId(), entityExt.getId());
            } else {
                Map<String, Object> param2 = new HashMap<>(16);
                param2.put("corpid", corpid);
                param2.put("formId", entityExt.getId());
                param2.put("businessType", businessType);
                param2.put("del", 0);
                List<PaasProcessDataEntity> paasProcessDataEntityList = paasProcessDataModel.list(param2);
                if (paasProcessDataEntityList.size() > 0) {
                    throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222062);
                }
            }
        }
        //删除template表
        workOrderTemplateModel.deleteByKey(templateId, corpid);

        //删除form
        if (!formEntityExtList.isEmpty()) {
            WorkOrderFormEntity entityExt = formEntityExtList.get(0);
            workOrderFormModel.deleteByKey(entityExt.getId(), corpid);
            //删除explain
            workOrderExplainModel.deleteByFormId(entityExt.getId(), corpid);
            // 删除表单时，需要更新关联列表的设置
            associationService.updateAssociation(corpid, entityExt.getId(), XbbRefTypeEnum.WORK_ORDER.getCode());
        }

        if (Objects.equals(workOrderTemplateEntity.getIsFree(), 0)) {
            param.clear();
            param.put("corpid", corpid);
            param.put("templateId", templateId);
            param.put("del", 0);
            workOrderStageModel.delete(param);
        }

        // 记录日志
        String userName = workOrderTemplateDelDTO.getLoginUserName();
        String name = workOrderTemplateEntity.getName();
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_FORM_WORK_ORDER_DELETE), userName, name);
        mongoLogHelp.buildLog(corpid, workOrderTemplateDelDTO.getUserId(), userName, OperateModuleTypeEnum.WORK_ORDER, OperateTypeEnum.DELETE, templateId.toString(), name, memo, workOrderTemplateDelDTO.getHttpHeader());

        WorkOrderTemplateDelVO workOrderTemplateDelVO = new WorkOrderTemplateDelVO();
        workOrderTemplateDelVO.setId(templateId);
        return workOrderTemplateDelVO;
    }

    @Override
    public WorkOrderTemplateEntity getByFormId(Long formId, String corpid) {
        WorkOrderFormEntity workOrderFormEntity = workOrderFormModel.getByKey(formId,corpid);
        return workOrderTemplateModel.getBykey(workOrderFormEntity.getTemplateId(),corpid);
    }

    @Override
    public Long updateTemplate(List<WorkOrderTemplateEntity> workOrderTemplateModelEntityList, MenuInitDTO menuInitDTO, Long category, UserEntity userEntity) throws XbbException {
        Long defaultID =0L;
        for (WorkOrderTemplateEntity workOrderTemplateEntity : workOrderTemplateModelEntityList) {
            if (Objects.equals(workOrderTemplateEntity.getIsDefault(),1)){
                workOrderTemplateEntity.setName("售后");
                workOrderTemplateEntity.setIntroduction("系统生成默认模板");
                workOrderTemplateEntity.setIsFree(1);
                workOrderTemplateEntity.setCc("[]");
                workOrderTemplateEntity.setEnable(1);
                JSONObject scopeRule = new JSONObject();
                scopeRule.put("inside", 1);
                scopeRule.put(OptionalRangeEnum.USER.getValue(), new JSONArray());
                scopeRule.put(OptionalRangeEnum.DEPT.getValue(),new JSONArray());
                workOrderTemplateEntity.setScopeRule(scopeRule.toJSONString());
                workOrderTemplateEntity.setCreatorId(userEntity.getUserId());
                workOrderTemplateEntity.setCreatorName(userEntity.getName());
                workOrderTemplateEntity.setModifierId(userEntity.getUserId());
                workOrderTemplateEntity.setModifierName(userEntity.getName());
                workOrderTemplateEntity.setExpectedTime(0);
                workOrderTemplateEntity.setDel(0);
                defaultID=workOrderTemplateEntity.getId();
            }else{
                workOrderTemplateEntity.setDel(DelEnum.DELETE.getDel());
            }
        }
        try {
            if (Objects.equals(defaultID,0L)){
                defaultID = initTemplate(menuInitDTO, category, userEntity);
            }else{
                workOrderTemplateModel.updateBatch(workOrderTemplateModelEntityList,menuInitDTO.getCorpid());
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("工单初始化菜单出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return defaultID;
    }
}
